#    Rubatom
#    Copyright (c) 2014 Sebastian Dufner
#
#    This file is part of Rubatom.
#
#    Rubatom is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Rubatom is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

require 'delegate'

class IO
  module Rubatom
    def read_many(*args)
      length = args.map {|arg| __rubatom_tr_type_to_s__(arg)}
          .reduce {|l, n| l + n}
      unpack_string = args.reduce('') do |result, type|
        result.concat __rubatom_tr_type_to_s__(type)
      end

      read(length).unpack(unpack_string)
    end

    def write_many(args)
      pack_string = args.values.flatten.reduce('') do |result, type|
        result.concat __rubatom_tr_type_to_s__(type)
      end

      write args.keys.flatten.pack(pack_string)
    end

  private

    def __rubatom_tr_type_to_s__(type)
      case type
      when 1, :ui8, :byte, :b, :uint8           then 'C'
      when 2, :i16, :short, :s, :int16, :uint16 then 'S>'
      when 4, :i32, :int, :int32, :i            then 'i>'
      when 8, :i64, :long, :int64, :ll, :li     then 'q>'
      when :f32, :float, :f                     then 'f>'
      when :f64, :double, :d                    then 'd>'
      when :byte_signed, :bs, :int8 , :i8       then 'c'
      else fail "unknown type: #{type}"
      end
    end

  end

  include self::Rubatom
end

class IODelegate < SimpleDelegator
  include IO::Rubatom
end

if StringIO
  class StringIO
    include IO::Rubatom
  end
end
